import android.provider.*;
import android.content.pm.PackageInstaller.*;
import android.content.pm.*;
import java.util.regex.*;
import dalvik.system.*;
import android.view.*;
import java.lang.reflect.*;
import android.content.*;
import android.app.*;
import android.widget.*;
import android.os.*;
import android.net.*;
import java.util.*;
import java.util.concurrent.*;
import java.io.*;
import java.net.*;
import android.webkit.*;

public class FuckZyb {
  private static int version = 20251007;
  private static String filesRootUrl = "https://gitee.com/caofangkuai/fuckzyb/raw/master/";

  private static Scanner input = new Scanner(System.in);

  public static void main(String[] args) {
    try {
      System.out.println("欢迎使用FuckZyb.java v" + version);
      System.out.println("开源地址: https://gitee.com/caofangkuai/fuckzyb/");
      System.out.println("By caofangkuai");
      System.out.println("检查更新中...");
      String jcgx = http_get(filesRootUrl + "FuckZyb.java");
      Pattern pattern = Pattern.compile("(?<=private static int version = )\\d+");
      Matcher matcher = pattern.matcher(jcgx);
      if (matcher.find()) {
        int newVersion = Integer.parseInt(matcher.group());
        if (newVersion > version) {
          System.out.println("发现新版本(v" + newVersion + ")，请前往仓库更新");
          return;
        } else {
          System.out.println("已是最新版本");
        }
      } else {
        System.out.println("检测更新失败");
      }
      System.out.println("初始化中(1s)...");
      Thread.sleep(1000);
      new RunOnHostContext(
          new RunOnHostContext.When() {
            @Override
            public void onRun(Context ApplicationCtx, Context ActivityCtx) {
              if (ApplicationCtx == null || ActivityCtx == null) {
                System.out.println("错误: 上下文环境为空");
                Looper.myLooper().quit();
                return;
              }
              if (!ActivityCtx.getPackageName().equals("com.cjtecapp.javaide")) {
                System.out.println("请在 Java编译器IDE(com.cjtecapp.javaide) 中运行!");
                Looper.myLooper().quit();
                return;
              }
              System.out.println("宿主Application上下文: " + ApplicationCtx);
              System.out.println("宿主Activity上下文: " + ActivityCtx);
              mainMenu(ApplicationCtx, ActivityCtx);
            }
          });
    } catch (Exception e) {
      System.out.println("发生错误: " + e.getMessage());
    }
  }

  private static void mainMenu(Context ApplicationCtx, Context ActivityCtx) {
    System.out.println("\n\n> 请选择要执行的项目:");
    System.out.println("(1) 唤起MTK工程模式");
    System.out.println("(2) MTK Easy Su");
    System.out.println("(3) 修改sys.allow.development");
    System.out.println("(4) 简易浏览器");
    System.out.println("(5) 超级低配黑盒");
    System.out.println("(6) 调用Android系统安装apk");
    if (Integer.parseInt(Build.VERSION.SECURITY_PATCH.replace("-", "")) >= 20200301) {
      System.out.println("注: 此设备的安全补丁在2020年3月之后，执行MTK Easy Root可能会有风险");
    }
    System.out.println("项目数字序号(按c退出):");
    if (input.hasNextLine()) {
      String str = input.nextLine();
      switch (str) {
        case "1":
          System.out.println("尝试唤起MTK工程模式");
          try {
            Intent intent = new Intent("android.provider.Telephony.SECRET_CODE");
            intent.setData(Uri.parse("android_secret_code://3646633"));
            intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
            ActivityCtx.sendBroadcast(intent);
          } catch (Exception e) {
            System.out.println("唤起失败，发生错误: " + e.getMessage());
          }
          mainMenu(ApplicationCtx, ActivityCtx);
          break;
        case "2":
          new ExploitHandler(
                  ActivityCtx,
                  true,
                  new CoroutineTask.OnPostExecute<ExploitResult>() {
                    @Override
                    public void onPostExecute(ExploitResult result) {
                      System.out.println("日志: " + result.log);
                      if (result.isSuccessful) {
                        System.out.println("执行成功");
                      } else {
                        System.out.println("执行失败");
                      }
                      System.out.println("由于系统bug，请手动退出");
                    }
                  })
              .execute();
          mainMenu(ApplicationCtx, ActivityCtx);
          break;
        case "3":
          Method sysPropGet = null;
          Method sysPropSet = null;
          try {
            Class<?> S = Class.forName("android.os.SystemProperties");
            Method M[] = S.getMethods();
            for (Method m : M) {
              String n = m.getName();
              if (n.equals("get")) {
                sysPropGet = m;
              } else if (n.equals("set")) {
                sysPropSet = m;
              }
            }
            String r = (String) sysPropGet.invoke(null, "sys.allow.development", "默认值(代表无法获取或不存在)");
            System.out.println(">>> 初始值: " + r);
            System.out.println(">>> 尝试修改sys.allow.development为true...");
            try {
              sysPropSet.invoke(null, "sys.allow.development", "true");
            } catch (Exception e) {
              System.out.println("修改失败,发生错误: " + e.getMessage() + "\n" + e.getCause());
              System.out.println(">>> 尝试方法2...");
              try {
                Class<?> SystemInfoUtil =
                    ActivityCtx.createPackageContext(
                            "com.zuoyebang.iot.pad.zpusercenter",
                            Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY)
                        .getClassLoader()
                        .loadClass("com.zuoyebang.iot.pad.developer.utils.SystemInfoUtil");
                SystemInfoUtil.getMethod("enableEnterDevelopModePage")
                    .invoke(SystemInfoUtil.getDeclaredConstructor().newInstance());
              } catch (Exception e1) {
                System.out.println("修改失败,发生错误: " + e1.getMessage() + "\n" + e1.getCause());
              }
            } finally {
              Thread.sleep(90); // 等待e.printStackTrace();
              r = (String) sysPropGet.invoke(null, "sys.allow.development", "默认值(代表无法获取或不存在)");
              System.out.println(">>> 当前值: " + r);
            }
          } catch (Exception e) {
            System.out.println("发生错误: " + e.getMessage());
          }
          mainMenu(ApplicationCtx, ActivityCtx);
          break;
        case "4":
          System.out.println("请输入要访问的网址:");
          if (input.hasNextLine()) {
            String url = input.nextLine();
            Handler handler = new Handler(Looper.getMainLooper());
            handler.post(
                new Runnable() {
                  @Override
                  public void run() {
                    showWebViewDialog(ActivityCtx, url);
                  }
                });
          }
          mainMenu(ApplicationCtx, ActivityCtx);
          break;
        case "5":
          System.out.println("请输入要运行的apk文件路径:");
          if (input.hasNextLine()) {
            File apk = new File(input.nextLine());
            if (apk.exists()) {
              System.out.println("下载依赖库中...");
              File dex = new File(ActivityCtx.getFilesDir(), "ApkRun.dex");
              downloadFile(filesRootUrl + "ApkRun.dex", dex);
              System.out.println("ApkRun.dex下载完成");
              Handler handler1 = new Handler(Looper.getMainLooper());
              handler1.post(
                  new Runnable() {
                    @Override
                    public void run() {
                      try {
                        DexClassLoader dexClassLoader =
                            new DexClassLoader(
                                dex.getAbsolutePath(),
                                ActivityCtx.getFilesDir().getAbsolutePath(),
                                null,
                                ActivityCtx.getClassLoader());
                        Class<?> clazz = dexClassLoader.loadClass("com.cfks.ApkRun.ApkRun");
                        Method runApk =
                            clazz.getMethod(
                                "runApk", Context.class, Context.class, File.class, Class.class);
                        runApk.invoke(
                            null,
                            ApplicationCtx,
                            ActivityCtx,
                            apk,
                            (Class<? extends Activity>)
                                ActivityCtx.getClassLoader()
                                    .loadClass("com.cjtecapp.javaide.mvvm.pay.MemberPayActivity"));
                      } catch (Exception e) {
                        System.out.println("发生错误: " + e.getMessage());
                      }
                    }
                  });
            } else {
              System.out.println("apk文件不存在");
            }
          }
          mainMenu(ApplicationCtx, ActivityCtx);
          break;
        case "6":
          if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
              && (!ActivityCtx.getPackageManager().canRequestPackageInstalls())) {
            // 引导用户手动开启权限
            System.out.println("请开启安装apk权限");
            Uri packageURI = Uri.parse("package:" + ActivityCtx.getPackageName());
            Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, packageURI);
            ActivityCtx.startActivity(intent);
          } else {
            // 已有权限，直接安装APK
            System.out.println("请输入要安装的apk文件路径:");
            if (input.hasNextLine()) {
              File apk = new File(input.nextLine());
              if (apk.exists()) {
                try {
                  System.out.println("下载依赖库中...");
                  File dex = new File(ActivityCtx.getFilesDir(), "QRomCommand.dex");
                  downloadFile(filesRootUrl + "QRomCommand.dex", dex);
                  System.out.println("QRomCommand.dex下载完成");
                  DexClassLoader dexClassLoader =
                      new DexClassLoader(
                          dex.getAbsolutePath(),
                          ActivityCtx.getFilesDir().getAbsolutePath(),
                          null,
                          ActivityCtx.getClassLoader());
                  Class<?> clazz = dexClassLoader.loadClass("qrom.component.root.Command");
                  Method main = clazz.getMethod("main", String[].class);
                  main.invoke(null, (Object) new String[] {"install", apk.getAbsolutePath()});
                } catch (Exception e) {
                  System.out.println("发生错误: " + e.getCause());
                  System.out.println(">> 尝试方法2...");
                  try {
                    PackageManagerCompatP.install(
                        ActivityCtx, apk.getAbsolutePath(), ActivityCtx.getPackageManager());
                  } catch (Exception e1) {
                    System.out.println("发生错误: " + e1.toString());
                  }
                }
              } else {
                System.out.println("apk文件不存在");
              }
            }
          }
          mainMenu(ApplicationCtx, ActivityCtx);
          break;
        case "c":
          Looper.myLooper().quit();
          return;
        default:
          mainMenu(ApplicationCtx, ActivityCtx);
          break;
      }
    }
  }

  private static class RunOnHostContext {
    public abstract static class When {
      public abstract void onRun(Context ApplicationCtx, Context ActivityCtx);
    }

    public RunOnHostContext(When when) {
      Looper.prepare();
      when.onRun(getHostContext(), getActivityContext());
      Looper.loop();
    }

    private static Context getHostContext() {
      try {
        Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
        Method currentApplication = activityThreadClass.getDeclaredMethod("currentApplication");
        Application app = (Application) currentApplication.invoke(null);
        return app;
      } catch (Exception e) {
        e.printStackTrace();
        return null;
      }
    }

    private static Context getActivityContext() {
      try {
        Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
        Method currentActivityThreadMethod =
            activityThreadClass.getDeclaredMethod("currentActivityThread");
        currentActivityThreadMethod.setAccessible(true);
        Object activityThread = currentActivityThreadMethod.invoke(null);

        Field activitiesField = activityThreadClass.getDeclaredField("mActivities");
        activitiesField.setAccessible(true);
        Map activities = (Map) activitiesField.get(activityThread);

        for (Object activityRecord : activities.values()) {
          Class<?> activityRecordClass = activityRecord.getClass();
          Field pausedField = activityRecordClass.getDeclaredField("paused");
          pausedField.setAccessible(true);
          if (!pausedField.getBoolean(activityRecord)) {
            Field activityField = activityRecordClass.getDeclaredField("activity");
            activityField.setAccessible(true);
            Activity activity = (Activity) activityField.get(activityRecord);
            if (activity != null) return activity;
          }
        }
      } catch (Exception e) {
        e.printStackTrace();
      }
      return null;
    }
  }

  private abstract static class CoroutineTask<T> {
    private final ExecutorService executorService;
    private final OnPostExecute<T> onPostExecute;
    private final Handler mainHandler;
    private boolean isCancelled;

    public CoroutineTask(OnPostExecute<T> onPostExecute) {
      this.executorService = Executors.newSingleThreadExecutor();
      this.onPostExecute = onPostExecute;
      this.mainHandler = new Handler(Looper.getMainLooper());
      this.isCancelled = false;
    }

    public void cancel() {
      isCancelled = true;
      executorService.shutdownNow();
    }

    public void execute() {
      onPreExecute();
      executorService.execute(
          () -> {
            T result = doInBackground();
            if (!isCancelled) {
              mainHandler.post(() -> onPostExecute.onPostExecute(result));
            }
          });
    }

    protected abstract void onPreExecute();

    protected abstract T doInBackground();

    public interface OnPostExecute<T> {
      void onPostExecute(T result);
    }
  }

  private static class ExploitResult {
    public boolean isSuccessful = false;
    public String log = "";

    public ExploitResult(boolean isSuccessful, String log) {
      this.isSuccessful = isSuccessful;
      this.log = log;
    }
  }

  private static class ExploitHandler extends CoroutineTask<ExploitResult> {
    private final Context context;
    boolean runAs64 = false;

    public ExploitHandler(
        Context context, boolean runAs64, OnPostExecute<ExploitResult> onPostExecute) {
      super(onPostExecute);
      this.context = context;
      this.runAs64 = runAs64;
    }

    @Override
    protected void onPreExecute() {
      System.out.println("执行中...");
    }

    @Override
    protected ExploitResult doInBackground() {
      StringBuilder log = new StringBuilder("Mtk-easy-su \n");
      List<File> files = new ArrayList<>();

      File dir64 = new File(context.getFilesDir(), "64");
      File dir32 = new File(context.getFilesDir(), "32");
      dir64.mkdir();
      dir32.mkdir();

      try {
        String[] filesUrl = {
          "magisk-boot.sh", "magiskinit32", "magiskinit64", "mtk-su32", "mtk-su64"
        };
        for (int i = 0; i < filesUrl.length; i++) {
          String name = filesUrl[i];
          File file;
          if (name.endsWith("32")) {
            file = new File(dir32, name.replace("32", ""));
          } else if (name.endsWith("64")) {
            file = new File(dir64, name.replace("64", ""));
          } else {
            file = new File(context.getFilesDir(), name);
          }

          System.out.println("下载" + name + "中...");
          downloadFile(filesRootUrl + name, file);

          Runtime.getRuntime().exec("chmod 510 " + file.getAbsolutePath()).waitFor();
          files.add(file);
          if (file.exists()) {
            log.append("extracted ")
                .append(file.toPath().relativize(context.getFilesDir().toPath()))
                .append("\n");
          }
        }
      } catch (Exception e) {
        log.append(e.getMessage());
      }

      String[] commands = {
        "getprop ro.vendor.product.model",
        "getprop ro.build.version.release",
        "date",
        "ls -R -1 -h -g " + context.getFilesDir().getAbsolutePath(),
        "cat /proc/cpuinfo",
        "cat /proc/meminfo",
        "free",
        "cat /proc/version",
        "sh "
            + new File(context.getFilesDir(), "magisk-boot.sh").getAbsolutePath()
            + " "
            + (runAs64 ? "64" : "32")
      };

      for (String command : commands) {
        try {
          log.append(getOutput(Runtime.getRuntime().exec(command)));
        } catch (Exception e) {
          log.append(e.getMessage());
        }
      }

      boolean isSuccessful = new File("/sbin/su").exists();

      try {
        for (File file : files) {
          if (file.delete()) {
            log.append("deleted ")
                .append(file.toPath().relativize(context.getFilesDir().toPath()))
                .append("\n");
          }
        }
      } catch (Exception e) {
        log.append(e.getMessage());
      }

      return new ExploitResult(isSuccessful, log.toString());
    }

    private String getOutput(java.lang.Process process) {
      String result = "";
      try {
        BufferedReader stdInput =
            new BufferedReader(new InputStreamReader(process.getInputStream()));
        String line;
        while ((line = stdInput.readLine()) != null) {
          result += line;
        }
      } catch (Exception e) {
        result = "";
      }
      return result;
    }
  }

  private static void showWebViewDialog(Context context, String url) {
    LinearLayout layout = new LinearLayout(context);
    layout.setOrientation(LinearLayout.VERTICAL);
    WebView webView = new WebView(context);
    webView.getSettings().setJavaScriptEnabled(true);
    webView.setWebViewClient(
        new WebViewClient() {
          @Override
          public boolean shouldOverrideUrlLoading(WebView view, String url) {
            webView.loadUrl(url);
            return false;
          }
        });
    LinearLayout.LayoutParams layoutParams =
        new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 1000);
    webView.setLayoutParams(layoutParams);
    webView.requestFocus(View.FOCUS_DOWN);
    webView.setEnabled(true);
    webView.setFocusable(true);
    webView.setFocusableInTouchMode(true);
    webView.loadUrl(url);
    layout.addView(webView);
    AlertDialog.Builder builder = new AlertDialog.Builder(context);
    builder
        .setTitle("WebView Dialog")
        .setView(layout)
        .setPositiveButton("前进", null)
        .setNegativeButton("后退", null)
        .setNeutralButton("刷新", null);
    AlertDialog dialog = builder.create();
    dialog.show();
    dialog
        .getButton(AlertDialog.BUTTON_POSITIVE)
        .setOnClickListener(
            v -> {
              if (webView.canGoForward()) webView.goForward();
            });
    dialog
        .getButton(AlertDialog.BUTTON_NEGATIVE)
        .setOnClickListener(
            v -> {
              if (webView.canGoBack()) webView.goBack();
            });
    dialog
        .getButton(AlertDialog.BUTTON_NEUTRAL)
        .setOnClickListener(
            v -> {
              webView.reload();
            });
  }

  private static void downloadFile(String url, File save) {
    try (BufferedInputStream in = new BufferedInputStream(new URL(url).openStream());
        FileOutputStream fileOutputStream = new FileOutputStream(save)) {
      byte dataBuffer[] = new byte[1024];
      int bytesRead;
      while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) {
        fileOutputStream.write(dataBuffer, 0, bytesRead);
      }
    } catch (Exception e) {
      System.out.println("发生错误: " + e.getMessage());
    }
  }

  private static String http_get(String url1) {
    try {
      URL url = new URL(url1);
      HttpURLConnection connection = (HttpURLConnection) url.openConnection();
      connection.setRequestMethod("GET");
      connection.setConnectTimeout(3000);
      connection.setReadTimeout(3000);

      int responseCode = connection.getResponseCode();
      if (responseCode == HttpURLConnection.HTTP_OK) {
        InputStream inputStream = connection.getInputStream();
        ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
        byte[] bytes = new byte[1024];
        int length;
        while ((length = inputStream.read(bytes)) != -1) {
          arrayOutputStream.write(bytes, 0, length);
        }
        return arrayOutputStream.toString();
      } else {
        return "-1";
      }
    } catch (Exception e) {
      return "-1";
    }
  }

  public static class PackageManagerCompatP {
    private static final String TAG = PackageManagerCompatP.class.getSimpleName();

    public static void install(Context context, String apkFilePath, PackageManager packageManager) {
      File apkFile = new File(apkFilePath);
      PackageInstaller packageInstaller = packageManager.getPackageInstaller();
      PackageInstaller.SessionParams sessionParams =
          new PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL);
      sessionParams.setSize(apkFile.length());

      int sessionId = createSession(packageInstaller, sessionParams);
      if (sessionId != -1) {
        boolean copySuccess = copyInstallFile(packageInstaller, sessionId, apkFilePath);
        if (copySuccess) {
          execInstallCommand(context, packageInstaller, sessionId);
        } else {
          System.out.println("复制apk到session失败");
        }
      } else {
        System.out.println("创建session失败");
      }
    }

    private static int createSession(
        PackageInstaller packageInstaller, PackageInstaller.SessionParams sessionParams) {
      System.out.println(">>> createSession");
      int sessionId = -1;
      try {
        sessionId = packageInstaller.createSession(sessionParams);
      } catch (Exception e) {
        e.printStackTrace();
      }
      return sessionId;
    }

    private static boolean copyInstallFile(
        PackageInstaller packageInstaller, int sessionId, String apkFilePath) {
      System.out.println(">>> copyInstallFile");
      InputStream in = null;
      OutputStream out = null;
      PackageInstaller.Session session = null;
      boolean success = false;
      try {
        File apkFile = new File(apkFilePath);
        session = packageInstaller.openSession(sessionId);
        out = session.openWrite("INSTALL_SESSION", 0, apkFile.length());
        in = new FileInputStream(apkFile);
        int total = 0, c;
        byte[] buffer = new byte[65536];
        while ((c = in.read(buffer)) != -1) {
          total += c;
          out.write(buffer, 0, c);
        }
        session.fsync(out);
        success = true;
      } catch (Exception e) {
        e.printStackTrace();
      } finally {
        closeQuietly(out);
        closeQuietly(in);
        closeQuietly(session);
      }
      return success;
    }

    private static void execInstallCommand(
        Context context, PackageInstaller packageInstaller, int sessionId) {
      System.out.println(">>> execInstallCommand");
      PackageInstaller.Session session = null;
      try {
        session = packageInstaller.openSession(sessionId);
        Intent intent =
            new Intent(
                context,
                new BroadcastReceiver() {
                  @Override
                  public void onReceive(Context context, Intent intent) {
                    if (intent != null) {
                      final int status =
                          intent.getIntExtra(
                              PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_FAILURE);
                      if (status == PackageInstaller.STATUS_SUCCESS) {
                        System.out.println("安装成功");
                      } else if (status == PackageInstaller.STATUS_PENDING_USER_ACTION) {
                        System.out.println("等待用户确认安装");
                        Intent confirmationIntent = intent.getParcelableExtra(Intent.EXTRA_INTENT);
                        confirmationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        try {
                          context.startActivity(confirmationIntent);
                        } catch (Exception e) {
                          System.out.println("发生错误: " + e.getMessage());
                        }
                      } else {
                        System.out.println("安装失败");
                      }
                    }
                  }
                }.getClass());
        PendingIntent pendingIntent =
            PendingIntent.getBroadcast(
                context, sessionId, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        session.commit(pendingIntent.getIntentSender());
      } catch (Exception e) {
        e.printStackTrace();
      } finally {
        closeQuietly(session);
      }
    }

    private static void closeQuietly(Closeable c) {
      System.out.println(">>> closeQuietly");
      if (c != null) {
        try {
          c.close();
        } catch (Exception ignored) {
          ignored.printStackTrace();
        }
      }
    }
  }
}
